/***************************************************************************
 *   Copyleft 2008-2009 by												   *
 *	 Iwanicki Krzysztof													   *
 *   <gamma.mini.pw.edu.pl/~iwanickik>									   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 ***************************************************************************/
#include "./vLogger.h"

namespace Vendetta {
	vChar vLogger::mBuffer [4096];
	vChar vLogger::mTimeBuffer [14];

	/**************************************************************
	* Other helpful functions                                     *
	***************************************************************/
	vVoid vLogger::Open(vBool bRedirect) {
		mOutput.open(mFileName.ToConstCharPtr());
		mRedirect = bRedirect;
#ifndef V_DEBUG
		mRedirect = false;
#endif
		printLogHeader();
		
		if (mRedirect) {
			// Opens console window
			AllocConsole();
			vInt hCrt;
			FILE *hf;
			mhConsoleWnd = ::GetStdHandle(STD_OUTPUT_HANDLE);
			hCrt = _open_osfhandle(*((vLong*) &mhConsoleWnd), _O_TEXT);
			hf = _fdopen(hCrt, "w");
			*stdout = *hf;
			setvbuf(stdout, NULL, _IONBF, 0);

			printLogConsoleHeader();
		}
	}

	vVoid vLogger::Info(const vChar *print, ...) {
		clearBuffer();

		va_list args;
		va_start(args, print);
		vsprintf_s(vLogger::mBuffer, print, args);
		va_end(args);

		mOutput<<"INFO: ";
		printTime();
		mOutput<<vLogger::mBuffer<<std::endl;

		if (mRedirect) {
			setColor(FOREGROUND_GREEN);
			std::cout<<vLogger::mTimeBuffer;
			std::cout<<vLogger::mBuffer<<std::endl;
		}
	}

	vVoid vLogger::Debug(const vChar* print, ...) {
		clearBuffer();

		va_list args;
		va_start(args, print);
		vsprintf_s(vLogger::mBuffer, print, args);
		va_end(args);
		
		mOutput<<"DEBUG: ";
		printTime();
		mOutput<<vLogger::mBuffer<<std::endl;

		if (mRedirect) {
			setColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
			std::cout<<vLogger::mTimeBuffer;
			std::cout<<vLogger::mBuffer<<std::endl;
		}
	}

	vVoid vLogger::Error(const vChar* print, ...) {
		clearBuffer();

		va_list args;
		va_start(args, print);
		vsprintf_s(vLogger::mBuffer, print, args);
		va_end(args) ;
		
		mOutput<<"ERROR: ";
		printTime();
		mOutput<<vLogger::mBuffer<<std::endl;

		if (mRedirect) {
			setColor(FOREGROUND_RED);
			std::cout<<vLogger::mTimeBuffer;
			std::cout<<vLogger::mBuffer<<std::endl;
		}
	}

	vVoid vLogger::Warning(const vChar* print, ...) {
		clearBuffer();

		va_list args;
		va_start(args, print);
		vsprintf_s(vLogger::mBuffer, print, args);
		va_end(args) ;
		
		mOutput<<"WARN: ";
		printTime();
		mOutput<<vLogger::mBuffer<<std::endl;

		if (mRedirect) {
			setColor(FOREGROUND_RED | FOREGROUND_GREEN);
			std::cout<<vLogger::mTimeBuffer;
			std::cout<<vLogger::mBuffer<<std::endl;
		}
	}

	vVoid vLogger::Close() {
		mOutput.close();

		if (mRedirect) {
			::FreeConsole();
		}
	}

	vVoid vLogger::printTime() {
		SYSTEMTIME time;
		clearTimeBuffer();

		::GetSystemTime(&time);
		sprintf_s(vLogger::mTimeBuffer, "[%02i:%02i:%02i] - ", time.wHour, time.wMinute, time.wSecond);
		mOutput<<vLogger::mTimeBuffer;
	}

	vVoid vLogger::clearBuffer() {
		ZeroMemory(vLogger::mBuffer, 4096 * sizeof(vChar));
	}

	vVoid vLogger::clearTimeBuffer() {
		::ZeroMemory(vLogger::mTimeBuffer, 14 * sizeof(vChar));
	}

	vVoid vLogger::setColor(vUShort color) {
		CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 
		vUShort wOldColorAttrs; 

		// Saves the current text colors.
		if (!::GetConsoleScreenBufferInfo(mhConsoleWnd, &csbiInfo)) {
			return;
		}
		wOldColorAttrs = csbiInfo.wAttributes;
		// Set the text attributes to draw red text on black background. 
		::SetConsoleTextAttribute(mhConsoleWnd, color | FOREGROUND_INTENSITY);
	}

	vVoid vLogger::printLogHeader() {
		mOutput<<"+-----------------------------------------------------------------------------+"<<std::endl;
		mOutput<<"|               Vendetta log system made by Iwanicki Krzysztof                |"<<std::endl;
		mOutput<<"|                  <http://gamma.mini.pw.edu.pl/~iwanickik>                   |"<<std::endl;
		mOutput<<"+-----------------------------------------------------------------------------+"<<std::endl;
	}

	vVoid vLogger::printLogConsoleHeader() {
		setColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
		std::cout<<"+-----------------------------------------------------------------------------+"<<std::endl;
		std::cout<<"|               ";
		setColor(FOREGROUND_GREEN | FOREGROUND_BLUE);
		std::cout<<"Vendetta log system made by Iwanicki Krzysztof";
		setColor(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
		std::cout<<"                |"<<std::endl;
		std::cout<<"|                  ";
		setColor(FOREGROUND_GREEN | FOREGROUND_BLUE);
		std::cout<<"<http://gamma.mini.pw.edu.pl/~iwanickik>";
		setColor(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
		std::cout<<"                   |"<<std::endl;
		std::cout<<"+-----------------------------------------------------------------------------+"<<std::endl;
		std::cout<<"| ";
		setColor(FOREGROUND_RED);
		std::cout<<"RED    - ERROR messages";
		setColor(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
		std::cout<<"                                                     |"<<std::endl;
		std::cout<<"| ";
		setColor(FOREGROUND_RED | FOREGROUND_GREEN);
		std::cout<<"YELLOW - WARNING messages";
		setColor(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
		std::cout<<"                                                   |"<<std::endl;	
		std::cout<<"| ";
		std::cout<<"WHITE  - DEBUG messages";
		std::cout<<"                                                     |"<<std::endl;
		std::cout<<"| ";
		setColor(FOREGROUND_GREEN);
		std::cout<<"GREEN  - INFO messages";
		setColor(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
		std::cout<<"                                                      |"<<std::endl;
		std::cout<<"+-----------------------------------------------------------------------------+"<<std::endl;
	}
}